using System;
using System.Collections.Generic;

namespace PropSys
{
    public class PropInt
    {
        private int _baseVal;
        private int _addVal;
        private int _pctVal;
        private int _adtVal;
        /// <summary>
        /// Buff reg.
        /// </summary>
        private Dictionary<string, Func<int>> _add;
        /// <summary>
        /// Buff reg.
        /// </summary>
        private Dictionary<string, Func<int>> _pct;
        /// <summary>
        /// Buff reg.
        /// </summary>
        private Dictionary<string, Func<int>> _adt;
        private Action ON_UpdAdd;
        private Action ON_UpdPct;
        private Action ON_UpdAdt;
        public int Val { get => (_baseVal + _addVal) * _pctVal + _adtVal; }

        public PropInt()
        {
            _add = new Dictionary<string, Func<int>>();
            _pct = new Dictionary<string, Func<int>>();
            _adt = new Dictionary<string, Func<int>>();
            ON_UpdAdd = delegate { };
            ON_UpdPct = delegate { };
            ON_UpdAdt = delegate { };
            _addVal = 0;
            _pctVal = 1;
            _adtVal = 0;
        }

        public PropInt(int baseVal) : this()
        {
            _baseVal = baseVal;
        }

        public void SetBaseVal(int baseVal)
        {
            _baseVal = baseVal;
        }

        private void UpdAdd()
        {
            _addVal = 0;
            foreach (Func<int> func in _add.Values) _addVal += func();
            ON_UpdAdd();
        }

        private void UpdPct()
        {
            _pctVal = 1;
            foreach (Func<int> func in _pct.Values) _pctVal *= 1 + func() / 100;
            ON_UpdPct();
        }

        private void UpdAdt()
        {
            _adtVal = 0;
            foreach (Func<int> func in _adt.Values) _adtVal += func();
            ON_UpdAdt();
        }

        public void RegVal(PropReg pr, string key, Func<int> val)
        {
            switch (pr)
            {
                case PropReg.ADD:
                    if (_add.ContainsKey(key)) _add[key] = val;
                    else _add.Add(key, val);
                    UpdAdd();
                    break;
                case PropReg.PCT:
                    if (_pct.ContainsKey(key)) _pct[key] = val;
                    else _pct.Add(key, val);
                    UpdPct();
                    break;
                case PropReg.ADT:
                    if (_adt.ContainsKey(key)) _adt[key] = val;
                    else _adt.Add(key, val);
                    UpdAdt();
                    break;
                default:
                    break;
            }
        }

        public void UregVal(PropReg pr, string key)
        {
            switch (pr)
            {
                case PropReg.ADD:
                    if (_add.ContainsKey(key)) _add.Remove(key);
                    UpdAdd();
                    break;
                case PropReg.PCT:
                    if (_pct.ContainsKey(key)) _pct.Remove(key);
                    UpdPct();
                    break;
                case PropReg.ADT:
                    if (_adt.ContainsKey(key)) _adt.Remove(key);
                    UpdAdt();
                    break;
                default:
                    break;
            }
        }

        public void RegUpdEvt(PropReg PR, Action action)
        {
            switch (PR)
            {
                case PropReg.ADD:
                    ON_UpdAdd += action;
                    break;
                case PropReg.PCT:
                    ON_UpdPct += action;
                    break;
                case PropReg.ADT:
                    ON_UpdAdt += action;
                    break;
                default:
                    break;
            }
        }

        public void UregUpdEvt(PropReg PR, Action action)
        {
            switch (PR)
            {
                case PropReg.ADD:
                    ON_UpdAdd -= action;
                    break;
                case PropReg.PCT:
                    ON_UpdPct -= action;
                    break;
                case PropReg.ADT:
                    ON_UpdAdt -= action;
                    break;
                default:
                    break;
            }
        }
    }
}
